package org.zoomdev.zoom.asm;

import org.objectweb.asm.Type;
import org.objectweb.asm.commons.Method;

import java.util.Arrays;

public class Instructions {
    public static Instruction loadThis() {
        return mg -> mg.loadThis();
    }

    public static Instruction loadArg(int index) {
        return mg -> mg.loadArg(index);
    }

    public static Instruction invokeVirtual(Class<?> owner, String methodName,
                                            Class<?> returnType, Class<?>... paramTypes) {
        return mg -> {
            mg.invokeVirtual(
                    Type.getType(owner),
                    new Method(methodName, Type.getType(returnType),
                            Arrays.stream(paramTypes).map(Type::getType).toArray(Type[]::new))
            );
        };
    }

    public static Instruction returnValue() {
        return mg -> mg.returnValue();
    }

    public static Instruction getField(Class<?> owner, String fieldName, Class<?> fieldType) {
        return mg -> mg.getField(Type.getType(owner), fieldName, Type.getType(fieldType));
    }

    public static Instruction putField(Class<?> owner, String fieldName, Class<?> fieldType) {
        return mg -> mg.putField(Type.getType(owner), fieldName, Type.getType(fieldType));
    }

    public static Instruction newInstance(Class<?> type) {
        return mg -> mg.newInstance(Type.getType(type));
    }

    public static Instruction dup() {
        return mg -> mg.dup();
    }

    public static Instruction push(Object value) {
        return mg -> {
            if (value instanceof Integer) {
                mg.push((Integer) value);
            } else if (value instanceof String) {
                mg.push((String) value);
            } else if (value instanceof Boolean) {
                mg.push((Boolean) value);
            } else {
                throw new IllegalArgumentException("Unsupported push type: " + value.getClass());
            }
        };
    }
}
